package com.espirit.eap.sa;

import java.util.Date;
import java.util.List;
import java.util.Map;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.espirit.common.Form;
import com.espirit.eap.manager.Department;
import com.espirit.eap.manager.DepartmentService;
import com.espirit.eap.pagelayout.ModelService;
import com.espirit.eap.pagelayout.SearchModelQuery;
import com.espirit.eap.util.StatGenericJPAService;
import com.googlecode.cswish.annotation.ParamScope;
import com.googlecode.cswish.annotation.Rest;
import com.googlecode.cswish.exception.ApplicationException;
import com.googlecode.cswish.model.PageElements;
import com.googlecode.cswish.model.PageInfo;
import com.googlecode.cswish.model.ParameterMap;
import com.googlecode.cswish.model.Reference;
import com.googlecode.cswish.oosearch.QLInfo;
import com.googlecode.cswish.struts.Action;
import com.googlecode.cswish.struts.spring.CacheSearchService;
import com.googlecode.cswish.struts.spring.CacheService;
import com.googlecode.cswish.struts.spring.Executor;
import com.googlecode.cswish.struts.spring.SearchCallback;
import com.googlecode.cswish.util.bean.ModelUtil;
import com.hr.SalaryAcctItem;
import com.hr.SalaryAcctItemService;
import com.hr.SchedualDefine;
import com.hr.SchedualDefineService;

@Service
public class EmployeeService {
	@Resource
	StatGenericJPAService genericService;
	
	@Resource
	SalaryAcctItemService salaryAcctItemService;
	
	@Resource
	CacheService cacheService;
	
	@Resource
	DepartmentService departmentService;
	
	@Resource
	ModelService modelService;
	
	@Resource
	CacheSearchService cacheSearchService;
	
	@Resource
	SchedualDefineService schedualDefineService;
	
	Map<String, String> employeeCache;
	
	@PersistenceContext(unitName="espirit")
	protected EntityManager em;
	
	
	@PostConstruct
	private void init() {
		employeeCache = cacheService.newCache(String.class);
	}
	public  PageInfo search(final ParameterMap model, int start, int limit,
    		String sort, String dir, boolean newSearch, Reference<QLInfo> qlInfoRef,
    		@ParamScope(visible=false, value="#ps")PageElements ps ,boolean fromMenu
    		) {
		
		SearchCallback callback = departmentService.buildDeptDefaultSearchCallback(model, null, null);
		return genericService.search(model, start, limit, sort, dir, newSearch, qlInfoRef, callback, true, false);
	}
	
	public void _add(Employee model , @ParamScope(visible=false, value="#ps")PageElements ps){
		
	}
	
	public void add(Employee model){
		checkDeptIds(model);
		model = genericService.add(model);
		salaryAcctItemService.onChanged();
	}
	
	public void _update(Employee model){
		model = genericService.view(model);
		if (model.getDepartment() != null){
			String deptIds = String.valueOf(model.getDepartment().getId());
			model.setDeptIds(deptIds);
		}
	}
	
	public void update(Employee model){
		checkDeptIds(model);
		Employee oldEmp = genericService.load(model);
		Department oldDept = oldEmp.getDepartment();
		Integer oldAttribute = oldEmp.getAttribute();
		
		model = (Employee) genericService.update(model);
		boolean deptChanged = false;
		boolean attributeChanged = false;
		if (oldDept == null){
			if (model.getDepartment() != null){
				deptChanged = true;
			}
		} else {
			if (model.getDepartment() == null){
				deptChanged = true;
			} else {
				if (!model.getDepartment().getId().equals(oldDept.getId())) {
					deptChanged = true;
				}
			}
		}
		
		if (oldAttribute == null){
			if (model.getAttribute() != null){
				attributeChanged = true;
			}
		} else {
			if (!oldAttribute.equals(model.getAttribute())){
				attributeChanged = true;
			}
		}
		
		if (deptChanged || attributeChanged){
			salaryAcctItemService.onChanged();
		}
	}
	
	private void checkDeptIds(Employee model){
		String deptIds = model.getDeptIds();
		if (deptIds != null) {
			int pos = deptIds.indexOf(",");
			if (pos > 0){
				throw new ApplicationException("只准选择一个部门");
			} else {
				model.setDepartment(new Department((deptIds)));
			}
		}
	}
	
	@Transactional
//	@Async
	public void importFile(EmployeeImport model){
		List<Object> updateModels = genericService.convertFileToModelList(model);
		int itemCount = 0;
		for (Object object : updateModels){
			Employee employee = (Employee)object;
			employee.setActive(Employee.ACTIVE_YES);
			Employee existed = getEmployeeByName(employee.getName());
			if (existed == null){
				add(employee);
			} else {
				ModelUtil.copyIgnoreNullValue(existed, employee);
				ModelUtil.copyIgnoreNullValue(employee, existed);
				genericService.merge(existed);
			}
			if (++itemCount % 100 == 0){
				em.flush();
				em.clear();
			}
		}
	}
	
	public Employee getEmployeeByName(String name){
		Employee example = new Employee();
		example.setName(name);
		return genericService.searchAll(example).getData(0);
	}
	
//	public Integer getEmployeeIdByDutyCardNbr(String dutyCardNbr){
//		if (dutyCardNbr == null)
//			return null;
//		if (employeeCache.get(dutyCardNbr) == null) {
//			Employee search = new Employee();
//			search.setDutyCardNbr(dutyCardNbr);
//			Employee theEmployee = genericService.searchAll(search).getData(0);
//			if (theEmployee == null) {
//				return null;
//			}
//			employeeCache.put(dutyCardNbr, theEmployee.getId());
//		}
//		return employeeCache.get(dutyCardNbr);
//	}
	
	public String getEmployeeIdByUserId(String userId){
		if (userId == null)
			return null;
		if (employeeCache.get(userId) == null) {
			Employee search = new Employee();
			search.setUserId(userId);
			Employee theEmployee = genericService.searchAll(search).getData(0);
			if (theEmployee == null) {
				return null;
			}
			employeeCache.put(userId, theEmployee.getId());
		}
		return employeeCache.get(userId);
	}
	
	public void cleanEmployeeDutyCardCach(){
		if (employeeCache != null){
			employeeCache.clear();
		}
	}
	
	public List<SalaryAcctItem> getSalaryAcctItems(String empId) {
		return salaryAcctItemService.getSalaryAcctItems(empId);
	}
	
	@Rest(type = Action.SEARCH)
	public PageInfo<Employee> searchInDepartment(Department model) {
//		if (model.getId() == null || model.getId().intValue() == 0) {
//			return genericService.searchAll(new Employee());
//		}
//
//		model = genericService.load(model);
//		Set<Department> departments = model.getDescendentChildren(Department.class);
//		if (departments == null) {
//			departments = Collections.EMPTY_SET;
//		}
//		String ql = "select a from " +  Employee.class.getName() + " a where a.department.id in ("
//				+ StringUtils.repeat("?,", departments.size()) + "?)";
//		List<Integer> params = new ArrayList<Integer>(departments.size() + 1);
//		params.add(model.getId());
//		for (Department childDepartment : departments) {
//			params.add(childDepartment.getId());
//		}
//
//		return genericService.searchByQl(new QLInfo(ql, true, params.toArray(new Integer[params.size()])), false);
		
		return null;
	}

	
	public void registerModelSearchType() {
		Executor<PageInfo, SearchModelQuery> employeeSearch = new Executor<PageInfo, SearchModelQuery>() {
			@Override
			public PageInfo execute(SearchModelQuery searchModelQuery) {
				String name = searchModelQuery.name;
				String labelProperty = searchModelQuery.labelProperty;
				String query = searchModelQuery.query;
				String filterProperty = searchModelQuery.filterProperty;
				String filter = searchModelQuery.filter;
				
				ParameterMap model = new ParameterMap();
				model.setModelName(name);
				if (query != null && query.length() > 0) {
					String quoteQuery = StringUtils.replace(query, "&", "\\&");
					model.setParameter(labelProperty, "|" + quoteQuery);
					model.setParameter("pinyin", "|" + quoteQuery);
				}
				if (filterProperty != null && filter != null && filter.length() > 0) {
					model.setParameter(filterProperty, filter);
				}
				boolean disablePermission = false;
				String sort = null;
				String dir = null;
				
				int start = (searchModelQuery.pageNo - 1) * searchModelQuery.pageSize;
				int limit = searchModelQuery.pageSize;
				
				
				PageInfo pageInfo = cacheSearchService.search(model, start, limit, sort, dir, false, true,
						null, null, searchModelQuery.statCount, disablePermission);
				return pageInfo;
			}
		};
		
		modelService.registerSearchType(Employee.class.getName(), employeeSearch);
	}
	
	public SchedualDefine getSchedualDefine(Integer empId){
		if (empId == null) return null;
				
		Employee employee = genericService.load(Employee.class, empId);
		if (employee == null || employee.getDepartment() == null) return null;
		
		return schedualDefineService.getSchedualDefineByDeptId(employee.getDepartment().getId());
	}
	
}
